package HLA1.control;


import HLA1.entity.Job;
import HLA1.generatori.GeneratoreIperEsponenziale;

import hla.rti.RTIexception;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author lorenzo
 */
public class gestioneCPU {
    private Simulatore s;

    public gestioneCPU(Simulatore s)
    {
        this.s = s;
    }

    	/*
		 * arrivoCpu
		 * gestice l'arrivo in cpu.
		 * viene preso il tempo minore tra quelli dei terminali, passato in cpu ed aumentato,
		 * se servito, con il tempo IperEsponenziale della CPU. In caso contrario viene messo in
		 * coda.
		 */
		public void arrivoCpu(){

			int index = s.getMinIndex();
			//prendo l'evento attuale
			Job evento = s.getCalendarioEventi().get(index);

			if(!s.cpu.occupato){ //se la cpu e' libera
			 s.cpu.occupato = true; //occupala
			 double tempo_attuale = s.getTempoCalendario(index); //prendi il tempo attuale dal calendario degli eventi
			 double nuovo_tempo = tempo_attuale + s.cpu.getGen().next(); //somma il tempo della cpu
			 evento.setTempoAttuale(nuovo_tempo); //aggiorna il tempo della cpu col nuovo tempo
			 s.getCalendarioEventi().set(s.getCalendarioEventi().size()-3, evento);
			}else{
				s.cpu.incrCountCoda();
                s.cpu.coda.addLast(evento); 
			}
 			s.getCalendarioEventi().set(index,new Job(999999.99)); //imposta il calendario al punto dell'arrivo con il tempo massimo
		}

        public void fineCpu(){
			int index = s.getMinIndex();
			double p_routing = s.getG().next(); //ci da la probabilita' di routing
			double tempo_clock = s.getTempoCalendario(index);
			//prendo l'evento attuale
			Job evento = s.getCalendarioEventi().get(index);

			//Routing verso Disco 1
			if(p_routing > 0.3){
				
                try {//dobbiamo mandare la i
//				*********************************************************************
//				System.out.println(s.simulazione.fedamb.federateTime + " chiedo a Fed2 tempoD1 per il job "+ evento.getIdJob());
//				*********************************************************************
				s.simulazione.mandaJob(s.simulazione.objectHandle, "d1", evento.getIdJob());
				s.simulazione.advanceTime(2.0);

			} catch (RTIexception ex) {
				Logger.getLogger(gestioneCPU.class.getName()).log(Level.SEVERE, null, ex);
			}

			//questo nel caso si riceve un tempo
			try {
				s.simulazione.advanceTime(1.0);
//				*********************************************************************
//				System.out.println("TEMPO FEDERAZIONE "+s.simulazione.fedamb.federateTime);
//				*********************************************************************
			} catch (RTIexception e) {
				e.printStackTrace();
			}
			while(s.simulazione.fedamb.ricevuto == false){
				try {
					System.out.println("#######################################################");
					System.out.println(s.simulazione.fedamb.federateTime+ " ATTENDO UN TEMPOD1");
					System.out.println("#######################################################");
					s.simulazione.advanceTime(1.0);
				} catch (RTIexception e) {
					e.printStackTrace();
				}
			}
			s.simulazione.fedamb.ricevuto = false;

                if(!s.simulazione.fedamb.disk1_occupato){ //se il disco 1 non e' occupato
					s.cpu.occupato = false;
					s.simulazione.fedamb.disk1_occupato = true;
					double tempo_al_disco1  = tempo_clock+ s.simulazione.fedamb.tempoD1;//this.gen3rl();
                    evento.setIngressoInCodaDisco(tempo_al_disco1);
					evento.setIngressoInDisco(tempo_al_disco1);
					s.getCalendarioEventi().set((s.getCalendarioEventi().size()-2), evento);
					s.getCalendarioEventi().set(index,new Job(999999.99));
     
				}else{
	                s.job1.add(evento);
                    evento.setIngressoInCodaDisco(tempo_clock);
					s.getCalendarioEventi().set(index,new Job(999999.99));
                }

			}

			//Routing verso Disco 2
			if(p_routing > 0.04 && p_routing <=0.3 )
			{
                try {//dobbiamo mandare la i
//				*********************************************************************
//				System.out.println(s.simulazione.fedamb.federateTime + " chiedo a Fed2 tempoD2 per il job "+ evento.getIdJob());
//				*********************************************************************
				s.simulazione.mandaJob(s.simulazione.objectHandle, "d2", evento.getIdJob());
				s.simulazione.advanceTime(2.0);

			} catch (RTIexception ex) {
				Logger.getLogger(gestioneCPU.class.getName()).log(Level.SEVERE, null, ex);
			}

			//questo nel caso si riceve un tempo
			try {
				s.simulazione.advanceTime(1.0);
//				*********************************************************************
//				System.out.println("TEMPO FEDERAZIONE "+s.simulazione.fedamb.federateTime);
//				*********************************************************************
			} catch (RTIexception e) {
				e.printStackTrace();
			}
			while(s.simulazione.fedamb.ricevuto == false){
				try {
					System.out.println("#######################################################");
					System.out.println(s.simulazione.fedamb.federateTime+ " ATTENDO UN TEMPOD2");
					System.out.println("#######################################################");
					s.simulazione.advanceTime(1.0);
				} catch (RTIexception e) {
					e.printStackTrace();
				}
			}
			s.simulazione.fedamb.ricevuto = false;
                if(!s.simulazione.fedamb.disk2_occupato){ //se il disco 2 non e' occupato
                        s.cpu.occupato = false;
						s.simulazione.fedamb.disk2_occupato = true;
						double tempo_al_disco2  = tempo_clock + s.simulazione.fedamb.tempoD2;
                        evento.setIngressoInCodaDisco(tempo_al_disco2);
						evento.setIngressoInDisco(tempo_al_disco2);
						s.getCalendarioEventi().set((s.getCalendarioEventi().size()-1), evento);
						s.getCalendarioEventi().set(index,new Job(999999.99));
    			}else{
                        s.job2.add(evento);
						evento.setIngressoInCodaDisco(tempo_clock);
						s.getCalendarioEventi().set(index,new Job(999999.99));
        		}
            }
			//Routing verso i terminali
			if(p_routing<0.04){
				s.set_JobCompletati(); //aumento job completati
				s.cpu.occupato = false;
				evento.setTempoRisposta(tempo_clock);
				s.completati.add(evento);
				s.getCalendarioEventi().set(index,new Job(999999.99));
         		//Genero un nuovo Comando da Terminale
				double tempo_arrivo = tempo_clock + ((GeneratoreIperEsponenziale)(s.cpu.getGen())).getGenE().next();    //this.genEsponenziale();
				for(int c=0;c<(s.getCalendarioEventi().size()-3);){
					if(s.getTempoCalendario(c)==999999.99){
						s.getCalendarioEventi().set(c,new Job(tempo_arrivo));
          			c = s.getCalendarioEventi().size()-3;
					}else{
						c++;
					}
				}
			}


			//Gestione coda cpu
			if (s.cpu.getCountCoda() ==0){
	            s.cpu.occupato=false;
			}else {
			            s.cpu.decrCountCoda();
			            s.cpu.occupato = true;
			            evento = s.cpu.coda.getFirst();
			            s.cpu.coda.removeFirst();
			            double tcpu = tempo_clock + s.cpu.getGen().next();
			            evento.setTempoAttuale(tcpu);
			            s.getCalendarioEventi().set(s.getCalendarioEventi().size()-3,evento);
			}

		}
}
